package service

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	core "ez/apps/core/document"
	"fmt"
	"gitee.com/dreamwood/ez-go/ez"
	"gitee.com/dreamwood/ez-go/tools"
	"gitee.com/dreamwood/ez-go/u"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
)

const EventUserLogin = "UserLogin"

func GenPass(password string, salt string) string {
	m5 := md5.New()
	_, _ = io.WriteString(m5, password+salt)
	return hex.EncodeToString(m5.Sum(nil))
}

func EncodeUserToken(user *core.User) (token string) {
	/*---------------
	Token生成规则：
	row 1: 写入UserId
	row 2: 写入当前时间戳
	row 3: 写入角色编码，多个用空格隔开
	*/
	user.LoadRoles()
	//取出Roles,如果为空，不允许访问
	roles := make([]string, 0)
	for _, role := range user.Roles {
		roles = append(roles, fmt.Sprintf("%d", role.Id))
	}
	//写入Id，写入当前时间戳
	originData := fmt.Sprintf("%d\n%d\n%s", user.Id, time.Now().Unix(), strings.Join(roles, " "))
	token = tools.AesEncrypt(originData, ez.ConfigCore.Vi)
	token = base64.StdEncoding.EncodeToString([]byte(token))
	return
}

func DecodeUserToken(token string) (uid int64, timestamp int64, roles []int64) {
	if token == "" {
		return
	}
	if data, err := base64.StdEncoding.DecodeString(token); err == nil {
		originData := tools.AesDecrypt(string(data), ez.ConfigCore.Vi)
		if strings.Contains(originData, "\n") {
			originDataArr := strings.Split(originData, "\n")
			if len(originDataArr) == 3 {
				uidd, _ := strconv.Atoi(originDataArr[0])
				uid = int64(uidd)
				ts, _ := strconv.Atoi(originDataArr[1])
				if ts > 0 {
					timestamp = int64(ts)
				}
				rolesStr := strings.Split(originDataArr[2], " ")
				for _, role := range rolesStr {
					roleInt, _ := strconv.Atoi(role)
					roles = append(roles, int64(roleInt))
				}
			}
		}
	}
	return
}

func GetTokenFromRequest(request *http.Request) string {
	token := request.Header.Get(ez.ConfigApi.AuthTokenName)
	return token
}

func CheckAndUpdateUserToken(response *http.Response) (newToken string) {
	request := response.Request
	if token := GetTokenFromRequest(request); token != "" {
		uid, t, _ := DecodeUserToken(token)
		//检查token是否过期
		if ez.ConfigApi.TokenExpire > 0 {
			//检查token是否过期
			if time.Now().Unix()-t > ez.ConfigApi.TokenExpire/2 {
				//租期过半就要续租
				crud := core.NewUserCrud()
				user, e := crud.FindId(uid)
				if e != nil {
					ez.LogToConsole(e.Error())
				} else {
					newToken = EncodeUserToken(user)
					user.Token = newToken
					user.Save()
					SetUserToRedis(user)
				}
			}
		}
	}
	return
}

func SetUserToRedis(user *core.User) {
	u.SetUserIdToRedis(user.Token, user.Id, ez.ConfigApi.TokenExpire)
	u.SetUserRolesToRedis(user.Token, user.RolesIds, ez.ConfigApi.TokenExpire)
}
